package com.openfarmanager.android.filesystem.actions.network;

import android.support.v4.app.FragmentManager;
import com.dropbox.client2.ProgressListener;
import com.dropbox.client2.exception.DropboxException;
import com.microsoft.live.LiveDownloadOperation;
import com.microsoft.live.LiveOperation;
import com.microsoft.live.LiveOperationException;
import com.openfarmanager.android.App;
import com.openfarmanager.android.core.network.dropbox.DropboxAPI;
import com.openfarmanager.android.core.network.skydrive.JsonKeys;
import com.openfarmanager.android.core.network.skydrive.SkyDriveAPI;
import com.openfarmanager.android.filesystem.DropboxFile;
import com.openfarmanager.android.filesystem.FileProxy;
import com.openfarmanager.android.filesystem.actions.FileActionTask;
import com.openfarmanager.android.model.NetworkEnum;
import com.openfarmanager.android.model.TaskStatusEnum;
import com.openfarmanager.android.model.exeptions.NetworkException;
import org.json.JSONException;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import static com.openfarmanager.android.model.TaskStatusEnum.*;

/**
 * @author Vlad Namashko
 */
public class CopyFromNetworkTask extends NetworkActionTask {

    protected String mDestination;
    protected List<FileProxy> mItems;

    public CopyFromNetworkTask(NetworkEnum networkType, FragmentManager fragmentManager, OnActionListener listener, List<FileProxy> items, String destination) {
        super(fragmentManager, listener, new ArrayList<File>());
        mDestination = destination;
        mItems = items;
        mNoProgress = true;
        mNetworkType = networkType;
    }

    @Override
    protected TaskStatusEnum doInBackground(Void... voids) {
        // TODO: hack
        totalSize = 1;

        return doCopy();
    }

    protected TaskStatusEnum doCopy() {

        for (FileProxy file : mItems) {
            if (isCancelled()) {
                return CANCELED;
            }
            try {
                switch (mNetworkType) {
                    case SkyDrive:
                        copyFromSkyDrive(file, mDestination);
                        break;
                    case Dropbox: default:
                        copyFromDropbox(file, mDestination);
                        break;
                }
            } catch (NullPointerException e) {
                return ERROR_FILE_NOT_EXISTS;
            } catch (InterruptedIOException e) {
                return CANCELED;
            } catch (IOException e) {
                return ERROR_COPY;
            } catch (IllegalArgumentException e) {
                return ERROR_COPY;
            } catch (DropboxException e) {
                return createNetworkError(NetworkException.handleDropboxException(e));
            } catch (LiveOperationException e) {
                return ERROR_COPY;
            } catch (Exception e) {
                return ERROR_COPY;
            }
        }
        return TaskStatusEnum.OK;
    }

    private void copyFromSkyDrive(FileProxy source, String destination) throws LiveOperationException, IOException, JSONException {
        SkyDriveAPI api = App.sInstance.getSkyDriveApi();
        if (isCancelled()) {
            throw new InterruptedIOException();
        }

        if (source.isDirectory()) {
            createDirectory(destination);

            List<FileProxy> list = api.getDirectoryFiles(source.getFullPath());
            for (FileProxy file : list) {
                copyFromSkyDrive(file, destination + "/" + source.getName());
            }
        } else {
            createDirectory(destination);

            File destinationFile = new File(destination + "/" + source.getName());
            if (!destinationFile.exists() && !destinationFile.createNewFile()) { }

            setCurrentFile(source);
            api.download(source, destinationFile);
        }

    }

    private void copyFromDropbox(FileProxy source, String destination) throws DropboxException, IOException {
        DropboxAPI api = App.sInstance.getDropboxApi();
        if (isCancelled()) {
            throw new InterruptedIOException();
        }
        if (source.isDirectory()) {
            try {
                createDirectory(destination);
                com.dropbox.client2.DropboxAPI.Entry currentNode = api.metadata(source.getFullPath(), -1, null, true, null);
                for (com.dropbox.client2.DropboxAPI.Entry entry : currentNode.contents) {
                    copyFromDropbox(new DropboxFile(entry), destination + "/" + source.getName());
                }
            } catch (Exception e) {
                throw NetworkException.handleDropboxException(e);
            }
        } else {
            createDirectory(destination);

            File destinationFile = new File(destination + "/" + source.getName());
            if (!destinationFile.exists() && !destinationFile.createNewFile()) { }

            setCurrentFile(source);
            api.getFile(source.getFullPath(), null, new FileOutputStream(destinationFile), null);
        }
    }

    private void createDirectory(String destination) {
        File destinationFolders = new File(destination);
        if (!destinationFolders.exists() && !destinationFolders.mkdirs()) { }
    }

    private void setCurrentFile(FileProxy source) {
        mCurrentFile = source.getName();
        updateProgress();
    }

}
